/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin			*/
/*	Project:	GlbCloud			*/
/*	Author:		gong_libin			*/
/*	Date:		2012_01_16			*/
/*	File:		MrMulti.cpp			*/
/********************************************************/

#include "MrMulti.h"

CMrMulti::CMrMulti()
{
	memset(&m_stMulti, '\0', sizeof(struct sockaddr_in));
}

CMrMulti::~CMrMulti()
{
}

void* CMrMulti::MrMultiGetMulti()
{
	return (void*)&m_stMulti;
}

void CMrMulti::MrMultiSetMulti(void* pAddr)
{
	memcpy(&m_stMulti, pAddr, sizeof(struct sockaddr_in));

	return;
}

int CMrMulti::MrNetInitSend(char* pszUrl)
{
	char* pszPort = NULL;
	int iReturn = MR_SUCCESS;

	if (NULL != (pszPort = CMrNet::MrNetUrl(pszUrl))) {
		iReturn = MrNetInitSend(pszUrl, pszPort);
	}
	else {
		iReturn = MR_FAILURE;
	}

	return iReturn;
}

int CMrMulti::MrNetInitRecv(char* pszUrl)
{
	char* pszPort = NULL;
	int iReturn = MR_SUCCESS;

	if (NULL != (pszPort = CMrNet::MrNetUrl(pszUrl))) {
		iReturn = MrNetInitRecv(pszUrl, pszPort);
	}
	else {
		iReturn = MR_FAILURE;
	}

	return iReturn;
}

int CMrMulti::MrNetInitSend(struct sockaddr_in* pstAddr)
{
	if (NULL != pstAddr) {
		memcpy(&m_stMulti, pstAddr, sizeof(struct sockaddr_in));
	}

	if (MR_SUCCESS != CMrNet::MrNetOpen(SOCK_DGRAM)) {
		return MR_FAILURE;
	}

	return MR_SUCCESS;
}

int CMrMulti::MrNetInitRecv(struct sockaddr_in* pstAddr)
{
	struct ip_mreq stMreq;

	if (NULL != pstAddr) {
		memcpy(&m_stMulti, pstAddr, sizeof(struct sockaddr_in));
	}

	memset(&stMreq, '\0', sizeof(struct ip_mreq));
	stMreq.imr_interface.s_addr = htonl(INADDR_ANY);
	stMreq.imr_multiaddr.s_addr = m_stMulti.sin_addr.s_addr;

	if (MR_SUCCESS != CMrNet::MrNetOpen(SOCK_DGRAM)) {
		return MR_FAILURE;
	}

	if (MR_SUCCESS != CMrNet::MrNetSetReuseAddr()) {
		return MR_FAILURE;
	}

	m_stMulti.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(CMrNet::m_iSocket, (struct sockaddr*)&m_stMulti, sizeof(struct sockaddr_in)) < 0) {
		MR_ERROR("%s\n", strerror(errno));
		CMrNet::MrNetClose();
		return MR_FAILURE;
	}

	if (setsockopt(CMrNet::m_iSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &stMreq, sizeof(struct ip_mreq)) < 0) {
		MR_ERROR("%s\n", strerror(errno));
		CMrNet::MrNetClose();
		return MR_FAILURE;
	}

	return MR_SUCCESS;
}

int CMrMulti::MrNetInitSend(char* pszAddress, char* pszPort)
{
	m_stMulti.sin_family = AF_INET;
	m_stMulti.sin_port = htons(atoi(pszPort));
	m_stMulti.sin_addr.s_addr = inet_addr(pszAddress);

	if (MR_SUCCESS != CMrNet::MrNetOpen(SOCK_DGRAM)) {
		return MR_FAILURE;
	}

	return MR_SUCCESS;
}

int CMrMulti::MrNetInitRecv(char* pszAddress, char* pszPort)
{
	struct ip_mreq stMreq;

	m_stMulti.sin_family = AF_INET;
	m_stMulti.sin_port = htons(atoi(pszPort));
	m_stMulti.sin_addr.s_addr = htonl(INADDR_ANY);

	if (MR_SUCCESS != CMrNet::MrNetOpen(SOCK_DGRAM)) {
		return MR_FAILURE;
	}

	if (MR_SUCCESS != CMrNet::MrNetSetReuseAddr()) {
		return MR_FAILURE;
	}

	if (bind(CMrNet::m_iSocket, (struct sockaddr*)&m_stMulti, sizeof(struct sockaddr_in)) < 0) {
		MR_ERROR("%s\n", strerror(errno));
		CMrNet::MrNetClose();
		return MR_FAILURE;
	}

	memset(&stMreq, '\0', sizeof(struct ip_mreq));
	stMreq.imr_interface.s_addr = htonl(INADDR_ANY);
	stMreq.imr_multiaddr.s_addr = inet_addr(pszAddress);

	if (setsockopt(CMrNet::m_iSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &stMreq, sizeof(struct ip_mreq)) < 0) {
		MR_ERROR("%s\n", strerror(errno));
		CMrNet::MrNetClose();
		return MR_FAILURE;
	}

	return MR_SUCCESS;
}

int CMrMulti::MrNetSend(UCHAR* puszPacket, int iLength)
{
	return sendto(CMrNet::m_iSocket, puszPacket, iLength, 0, (struct sockaddr*)&m_stMulti, sizeof(struct sockaddr_in));
}

int CMrMulti::MrNetRecv(UCHAR* puszPacket, int iLength)
{
	int iMulti = sizeof(struct sockaddr_in);

	return recvfrom(CMrNet::m_iSocket, puszPacket, iLength, 0, (struct sockaddr*)&m_stMulti, (socklen_t*)&iMulti);
}

int CMrMulti::MrNetSendAll(UCHAR* puszPacket, int iLength)
{
	int iCount = 0;
	int iTotal = 0;

	while (iTotal < iLength) {
		if ((iCount = MrNetSend(puszPacket + iTotal, iLength - iTotal)) > 0) {
			iTotal += iCount;
		}
		else {
			MR_ERROR("%s\n", strerror(errno));
			break;
		}
	}

	return iTotal;
}

int CMrMulti::MrNetRecvAll(UCHAR* puszPacket, int iLength)
{
	int iCount = 0;
	int iTotal = 0;

	while (iTotal < iLength) {
		if ((iCount = MrNetRecv(puszPacket + iTotal, iLength - iTotal)) > 0) {
			iTotal += iCount;
		}
		else {
			MR_ERROR("%s\n", strerror(errno));
			break;
		}
	}

	return iTotal;
}
